// 组合式函数库
import { ref, reactive, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
import { debounce, throttle, storage, getDeviceType, isMobile } from '@/utils'
import API from '@/api'
import type { Ref, ComputedRef } from 'vue'

/**
 * 加载状态管理
 */
export function useLoading(initialState = false) {
  const loading = ref(initialState)
  const loadingInstance = ref<any>(null)
  
  const setLoading = (state: boolean, options?: any) => {
    loading.value = state
    
    if (state && options) {
      loadingInstance.value = ElLoading.service(options)
    } else if (!state && loadingInstance.value) {
      loadingInstance.value.close()
      loadingInstance.value = null
    }
  }
  
  const withLoading = async <T>(fn: () => Promise<T>, options?: any): Promise<T> => {
    setLoading(true, options)
    try {
      const result = await fn()
      return result
    } finally {
      setLoading(false)
    }
  }
  
  return {
    loading: readonly(loading),
    setLoading,
    withLoading
  }
}

/**
 * 分页管理
 */
export function usePagination(initialPageSize = 10) {
  const pagination = reactive({
    current: 1,
    pageSize: initialPageSize,
    total: 0,
    showSizeChanger: true,
    showQuickJumper: true,
    showTotal: true,
    pageSizeOptions: ['10', '20', '50', '100']
  })
  
  const handlePageChange = (page: number) => {
    pagination.current = page
  }
  
  const handlePageSizeChange = (pageSize: number) => {
    pagination.pageSize = pageSize
    pagination.current = 1
  }
  
  const resetPagination = () => {
    pagination.current = 1
    pagination.total = 0
  }
  
  const setPagination = (data: { current?: number; pageSize?: number; total?: number }) => {
    Object.assign(pagination, data)
  }
  
  return {
    pagination,
    handlePageChange,
    handlePageSizeChange,
    resetPagination,
    setPagination
  }
}

/**
 * 表单验证
 */
export function useFormValidation() {
  const errors = ref<Record<string, string>>({})
  
  const validateField = (field: string, value: any, rules: any[]) => {
    for (const rule of rules) {
      if (rule.required && (!value || value.toString().trim() === '')) {
        errors.value[field] = rule.message || `${field}不能为空`
        return false
      }
      
      if (rule.min && value.length < rule.min) {
        errors.value[field] = rule.message || `${field}长度不能少于${rule.min}个字符`
        return false
      }
      
      if (rule.max && value.length > rule.max) {
        errors.value[field] = rule.message || `${field}长度不能超过${rule.max}个字符`
        return false
      }
      
      if (rule.pattern && !rule.pattern.test(value)) {
        errors.value[field] = rule.message || `${field}格式不正确`
        return false
      }
      
      if (rule.validator && !rule.validator(value)) {
        errors.value[field] = rule.message || `${field}验证失败`
        return false
      }
    }
    
    delete errors.value[field]
    return true
  }
  
  const validateForm = (form: Record<string, any>, rules: Record<string, any[]>) => {
    let isValid = true
    
    for (const field in rules) {
      if (!validateField(field, form[field], rules[field])) {
        isValid = false
      }
    }
    
    return isValid
  }
  
  const clearErrors = () => {
    errors.value = {}
  }
  
  const clearFieldError = (field: string) => {
    delete errors.value[field]
  }
  
  return {
    errors: readonly(errors),
    validateField,
    validateForm,
    clearErrors,
    clearFieldError
  }
}

/**
 * 搜索功能
 */
export function useSearch<T>(searchFn: (keyword: string) => Promise<T[]>, delay = 300) {
  const keyword = ref('')
  const results = ref<T[]>([])
  const { loading, setLoading } = useLoading()
  
  const debouncedSearch = debounce(async (searchKeyword: string) => {
    if (!searchKeyword.trim()) {
      results.value = []
      return
    }
    
    setLoading(true)
    try {
      const data = await searchFn(searchKeyword)
      results.value = data
    } catch (error) {
      console.error('Search error:', error)
      results.value = []
    } finally {
      setLoading(false)
    }
  }, delay)
  
  watch(keyword, (newKeyword) => {
    debouncedSearch(newKeyword)
  })
  
  const clearSearch = () => {
    keyword.value = ''
    results.value = []
  }
  
  return {
    keyword,
    results: readonly(results),
    loading,
    clearSearch
  }
}

/**
 * 本地存储
 */
export function useStorage<T>(key: string, defaultValue?: T) {
  const storedValue = storage.get<T>(key, defaultValue)
  const value = ref<T>(storedValue)
  
  const setValue = (newValue: T) => {
    value.value = newValue
    storage.set(key, newValue)
  }
  
  const removeValue = () => {
    value.value = defaultValue as T
    storage.remove(key)
  }
  
  // 监听值变化，自动保存
  watch(value, (newValue) => {
    storage.set(key, newValue)
  }, { deep: true })
  
  return {
    value,
    setValue,
    removeValue
  }
}

/**
 * 响应式设计
 */
export function useResponsive() {
  const deviceType = ref(getDeviceType())
  const isMobileDevice = ref(isMobile())
  const windowWidth = ref(window.innerWidth)
  const windowHeight = ref(window.innerHeight)
  
  const isDesktop = computed(() => deviceType.value === 'desktop')
  const isTablet = computed(() => deviceType.value === 'tablet')
  const isMobileView = computed(() => deviceType.value === 'mobile')
  
  const updateDeviceInfo = throttle(() => {
    deviceType.value = getDeviceType()
    windowWidth.value = window.innerWidth
    windowHeight.value = window.innerHeight
  }, 100)
  
  onMounted(() => {
    window.addEventListener('resize', updateDeviceInfo)
  })
  
  onUnmounted(() => {
    window.removeEventListener('resize', updateDeviceInfo)
  })
  
  return {
    deviceType: readonly(deviceType),
    isMobileDevice: readonly(isMobileDevice),
    windowWidth: readonly(windowWidth),
    windowHeight: readonly(windowHeight),
    isDesktop,
    isTablet,
    isMobileView
  }
}

/**
 * 滚动监听
 */
export function useScroll() {
  const scrollTop = ref(0)
  const scrollLeft = ref(0)
  const isScrolling = ref(false)
  
  const updateScrollPosition = throttle(() => {
    scrollTop.value = window.pageYOffset || document.documentElement.scrollTop
    scrollLeft.value = window.pageXOffset || document.documentElement.scrollLeft
  }, 10)
  
  const handleScroll = () => {
    isScrolling.value = true
    updateScrollPosition()
    
    // 滚动结束检测
    clearTimeout(scrollTimer)
    scrollTimer = setTimeout(() => {
      isScrolling.value = false
    }, 150)
  }
  
  let scrollTimer: NodeJS.Timeout
  
  onMounted(() => {
    window.addEventListener('scroll', handleScroll, { passive: true })
    updateScrollPosition()
  })
  
  onUnmounted(() => {
    window.removeEventListener('scroll', handleScroll)
    clearTimeout(scrollTimer)
  })
  
  return {
    scrollTop: readonly(scrollTop),
    scrollLeft: readonly(scrollLeft),
    isScrolling: readonly(isScrolling)
  }
}

/**
 * 回到顶部
 */
export function useBackToTop(threshold = 300) {
  const { scrollTop } = useScroll()
  const showBackToTop = computed(() => scrollTop.value > threshold)
  
  const backToTop = () => {
    window.scrollTo({
      top: 0,
      behavior: 'smooth'
    })
  }
  
  return {
    showBackToTop,
    backToTop
  }
}

/**
 * 图片懒加载
 */
export function useLazyLoad() {
  const observer = ref<IntersectionObserver | null>(null)
  
  const observe = (element: Element) => {
    if (!observer.value) {
      observer.value = new IntersectionObserver(
        (entries) => {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              const img = entry.target as HTMLImageElement
              const src = img.dataset.src
              
              if (src) {
                img.src = src
                img.removeAttribute('data-src')
                observer.value?.unobserve(img)
              }
            }
          })
        },
        {
          rootMargin: '50px'
        }
      )
    }
    
    observer.value.observe(element)
  }
  
  const unobserve = (element: Element) => {
    observer.value?.unobserve(element)
  }
  
  onUnmounted(() => {
    observer.value?.disconnect()
  })
  
  return {
    observe,
    unobserve
  }
}

/**
 * 复制到剪贴板
 */
export function useClipboard() {
  const copy = async (text: string) => {
    try {
      if (navigator.clipboard) {
        await navigator.clipboard.writeText(text)
      } else {
        // 降级方案
        const textArea = document.createElement('textarea')
        textArea.value = text
        textArea.style.position = 'fixed'
        textArea.style.left = '-999999px'
        textArea.style.top = '-999999px'
        document.body.appendChild(textArea)
        textArea.focus()
        textArea.select()
        document.execCommand('copy')
        document.body.removeChild(textArea)
      }
      
      ElMessage.success('复制成功')
      return true
    } catch (error) {
      ElMessage.error('复制失败')
      return false
    }
  }
  
  return {
    copy
  }
}

/**
 * 确认对话框
 */
export function useConfirm() {
  const confirm = (message: string, title = '确认', options?: any) => {
    return ElMessageBox.confirm(message, title, {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
      ...options
    })
  }
  
  const deleteConfirm = (message = '此操作将永久删除该数据，是否继续？') => {
    return confirm(message, '删除确认', {
      confirmButtonText: '删除',
      confirmButtonClass: 'el-button--danger',
      type: 'error'
    })
  }
  
  return {
    confirm,
    deleteConfirm
  }
}

/**
 * 文件上传
 */
export function useFileUpload() {
  const uploading = ref(false)
  const uploadProgress = ref(0)
  
  const uploadFile = async (file: File, onProgress?: (progress: number) => void) => {
    uploading.value = true
    uploadProgress.value = 0
    
    try {
      const response = await API.upload.uploadFile(file)
      
      // 模拟上传进度
      const progressInterval = setInterval(() => {
        if (uploadProgress.value < 90) {
          uploadProgress.value += 10
          onProgress?.(uploadProgress.value)
        }
      }, 100)
      
      // 完成上传
      setTimeout(() => {
        clearInterval(progressInterval)
        uploadProgress.value = 100
        onProgress?.(100)
      }, 1000)
      
      return response.data
    } catch (error) {
      ElMessage.error('上传失败')
      throw error
    } finally {
      uploading.value = false
    }
  }
  
  const uploadFiles = async (files: File[], onProgress?: (progress: number) => void) => {
    const results = []
    
    for (let i = 0; i < files.length; i++) {
      const result = await uploadFile(files[i], (progress) => {
        const totalProgress = ((i + progress / 100) / files.length) * 100
        onProgress?.(totalProgress)
      })
      results.push(result)
    }
    
    return results
  }
  
  return {
    uploading: readonly(uploading),
    uploadProgress: readonly(uploadProgress),
    uploadFile,
    uploadFiles
  }
}

/**
 * 表格管理
 */
export function useTable<T>(fetchFn: (params: any) => Promise<{ data: T[]; total: number }>) {
  const data = ref<T[]>([])
  const { loading, setLoading } = useLoading()
  const { pagination, handlePageChange, handlePageSizeChange, resetPagination } = usePagination()
  const selectedRows = ref<T[]>([])
  
  const fetchData = async (params?: any) => {
    setLoading(true)
    try {
      const response = await fetchFn({
        page: pagination.current,
        pageSize: pagination.pageSize,
        ...params
      })
      
      data.value = response.data
      pagination.total = response.total
    } catch (error) {
      console.error('Fetch data error:', error)
      data.value = []
    } finally {
      setLoading(false)
    }
  }
  
  const refresh = () => {
    fetchData()
  }
  
  const handleSelectionChange = (selection: T[]) => {
    selectedRows.value = selection
  }
  
  // 监听分页变化
  watch([() => pagination.current, () => pagination.pageSize], () => {
    fetchData()
  })
  
  onMounted(() => {
    fetchData()
  })
  
  return {
    data: readonly(data),
    loading,
    pagination,
    selectedRows: readonly(selectedRows),
    fetchData,
    refresh,
    handlePageChange,
    handlePageSizeChange,
    handleSelectionChange,
    resetPagination
  }
}

/**
 * 路由管理
 */
export function useRouteHelper() {
  const router = useRouter()
  const route = useRoute()
  
  const goBack = () => {
    if (window.history.length > 1) {
      router.go(-1)
    } else {
      router.push('/')
    }
  }
  
  const goHome = () => {
    router.push('/')
  }
  
  const openInNewTab = (path: string) => {
    const routeData = router.resolve(path)
    window.open(routeData.href, '_blank')
  }
  
  const getQueryParam = (key: string, defaultValue?: string) => {
    return route.query[key] as string || defaultValue
  }
  
  const setQueryParam = (key: string, value: string) => {
    router.push({
      query: {
        ...route.query,
        [key]: value
      }
    })
  }
  
  return {
    router,
    route,
    goBack,
    goHome,
    openInNewTab,
    getQueryParam,
    setQueryParam
  }
}

/**
 * 主题管理
 */
export function useTheme() {
  const { value: theme, setValue: setTheme } = useStorage('theme', 'light')
  
  const isDark = computed(() => theme.value === 'dark')
  const isLight = computed(() => theme.value === 'light')
  
  const toggleTheme = () => {
    setTheme(isDark.value ? 'light' : 'dark')
  }
  
  const applyTheme = () => {
    document.documentElement.setAttribute('data-theme', theme.value)
    document.documentElement.classList.toggle('dark', isDark.value)
  }
  
  // 应用主题
  watch(theme, applyTheme, { immediate: true })
  
  return {
    theme,
    isDark,
    isLight,
    setTheme,
    toggleTheme
  }
}

/**
 * 国际化
 */
export function useI18n() {
  const { value: locale, setValue: setLocale } = useStorage('locale', 'zh-CN')
  
  const isZhCN = computed(() => locale.value === 'zh-CN')
  const isEnUS = computed(() => locale.value === 'en-US')
  
  const toggleLocale = () => {
    setLocale(isZhCN.value ? 'en-US' : 'zh-CN')
  }
  
  return {
    locale,
    isZhCN,
    isEnUS,
    setLocale,
    toggleLocale
  }
}

// 导出所有组合式函数
export {
  useLoading,
  usePagination,
  useFormValidation,
  useSearch,
  useStorage,
  useResponsive,
  useScroll,
  useBackToTop,
  useLazyLoad,
  useClipboard,
  useConfirm,
  useFileUpload,
  useTable,
  useRouteHelper,
  useTheme,
  useI18n
}